/*
============================================================================
 Name        : nmsJpegDct.c
 Author      : Jian
 Version     :
 Copyright   : base on http://ce.sharif.edu/~ahmadinejad/jpeg/
 Description : nmsJpegDct.c - source file
============================================================================
*/

/* INCLUDE FILES */
#include "nmsJpegDct.h"
#include "nmsJpegDefine.h"


#ifdef __NMS_JPEG_DCT_USE_FLOAT

"Warnning: float is too slow" !

typedef float nmsFloatMatrix[8][8] ;

static const float C2arr[8]= {.35355339059327376220,.5,.5,.5,.5,.5,.5,.5};

static const float _cosVal[200] = {
    1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220, 0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330, -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804, -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123,
    -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220, -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330, 0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804, 1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220,
    0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330, -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804, -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123, -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220, -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330,
    0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804, 1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220, 0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330, -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804,
    -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123, -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220, -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330, 0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804, 1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123,
    0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220, -0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330, -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804, -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123, -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220,
    -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330, 0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804, 1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220, -0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330,
    -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804, -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123, -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220, -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330, 0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804,
    1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220, -0.0000000000, -0.1950903220, -0.3826834324, -0.5555702330, -0.7071067812, -0.8314696123, -0.9238795325, -0.9807852804, -1.0000000000, -0.9807852804, -0.9238795325, -0.8314696123,
    -0.7071067812, -0.5555702330, -0.3826834324, -0.1950903220, -0.0000000000, 0.1950903220, 0.3826834324, 0.5555702330, 0.7071067812, 0.8314696123, 0.9238795325, 0.9807852804, 1.0000000000, 0.9807852804, 0.9238795325, 0.8314696123, 0.7071067812, 0.5555702330, 0.3826834324, 0.1950903220
} ;

static __NMS_INLINE void _transpose(float (*a)[8])
{
    int i,j;
    for (i=0; i<8; i++)
        for (j=i+1; j<8; j++) {
            float t=a[i][j];
            a[i][j]=a[j][i];
            a[j][i]=t;
        }
}

static __NMS_INLINE void _idctonrow(float *a, float *b)
{
    int i, k ;
    for (i=0; i<8; i++) {
        b[i]=0;
        for (k=0; k<8; k++)
            b[i]+=(C2arr[k])*a[k]*_cosVal[k*(2*i+1)];
    }
}

static __NMS_INLINE void _dctonrow(float *a, float *b)
{
    int i, k ;
    for (i=0; i<8; i++) {
        b[i]=0;
        for (k=0; k<8; k++)
            b[i]+=a[k]*_cosVal[i*(2*k+1)];
        b[i]*=C2arr[i];
    }
}

static __NMS_INLINE void _idct2(float (*a)[8], float (*b)[8])
{
    float c[8][8];
    int i;
    for (i=0; i<8; i++)
        _idctonrow(a[i],c[i]);
    _transpose(c);
    for (i=0; i<8; i++)
        _idctonrow(c[i],b[i]);
    _transpose(b);
}

static __NMS_INLINE void _dct2(float (*a)[8], float (*b)[8])
{
    float c[8][8];
    int i;
    for (i=0; i<8; i++)
        _dctonrow(a[i],c[i]);
    _transpose(c);
    for (i=0; i<8; i++)
        _dctonrow(c[i],b[i]);
    _transpose(b);
}

static __NMS_INLINE int __floor(double d)
{
    return (d < -0.00000000000000001) ? ((int)d - 1) : ((int)d) ;
}

void nmsJpegIdct(const int (*a)[8], int (*b)[8])
{
    int i,j;
    nmsFloatMatrix c,d;

    for (i=0; i<8; i++)
        for (j=0; j<8; j++)
            c[i][j]=a[i][j];
    _idct2(c,d);
    for (i=0; i<8; i++)
        for (j=0; j<8; j++)
            b[i][j] = __floor(d[i][j]+0.5);
}

void nmsJpegDct(const int (*a)[8], int (*b)[8])
{
    int i,j;
    nmsFloatMatrix c,d;
    for (i=0; i<8; i++)
        for (j=0; j<8; j++)
            c[i][j]=a[i][j];
    _dct2(c,d);
    for (i=0; i<8; i++)
        for (j=0; j<8; j++) {
            b[i][j]=(int)(d[i][j]+0.5);
            if (b[i][j]<-1023) b[i][j]=-1023;
            if (b[i][j]>1023) b[i][j]=1023;
        }
}

#else

static const int C2arr[8]= {3535,5000,5000,5000,5000,5000,5000,5000};

static const int _cosVal[200] = {
    10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950, 0, -1950, -3826, -5555, -7071, -8314, -9238, -9807, -10000, -9807, -9238, -8314,
    -7071, -5555, -3826, -1950, 0, 1950, 3826, 5555, 7071, 8314, 9238, 9807, 10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950,
    0, -1950, -3826, -5555, -7071, -8314, -9238, -9807, -10000, -9807, -9238, -8314, -7071, -5555, -3826, -1950, 0, 1950, 3826, 5555,
    7071, 8314, 9238, 9807, 10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950, 0, -1950, -3826, -5555, -7071, -8314, -9238, -9807,
    -10000, -9807, -9238, -8314, -7071, -5555, -3826, -1950, 0, 1950, 3826, 5555, 7071, 8314, 9238, 9807, 10000, 9807, 9238, 8314,
    7071, 5555, 3826, 1950, 0, -1950, -3826, -5555, -7071, -8314, -9238, -9807, -10000, -9807, -9238, -8314, -7071, -5555, -3826, -1950,
    0, 1950, 3826, 5555, 7071, 8314, 9238, 9807, 10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950, 0, -1950, -3826, -5555,
    -7071, -8314, -9238, -9807, -10000, -9807, -9238, -8314, -7071, -5555, -3826, -1950, 0, 1950, 3826, 5555, 7071, 8314, 9238, 9807,
    10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950, 0, -1950, -3826, -5555, -7071, -8314, -9238, -9807, -10000, -9807, -9238, -8314,
    -7071, -5555, -3826, -1950, 0, 1950, 3826, 5555, 7071, 8314, 9238, 9807, 10000, 9807, 9238, 8314, 7071, 5555, 3826, 1950
} ;

static __NMS_INLINE void _transpose(int (*a)[8])
{
    int i,j;
    for (i=0; i<8; i++)
        for (j=i+1; j<8; j++) {
            int t=a[i][j];
            a[i][j]=a[j][i];
            a[j][i]=t;
        }
}

static __NMS_INLINE void _idctonrow(const int *a, int *b)
{
    int i, k ;
    int tmp ;
    for (i=0; i<8; i++) {
        tmp = 0 ;
        for (k=0; k<8; k++) {
            tmp += (((int)((C2arr[k])*_cosVal[k*(2*i+1)]) / 1000) * a[k]);
        }
        b[i] = tmp / 100000 ;
    }
}

static __NMS_INLINE void _dctonrow(const int *a, int *b)
{
    int i, k ;
    int tmp ;
    for (i=0; i<8; i++) {
        tmp = 0 ;
        for (k=0; k<8; k++)
            tmp += ((int)a[k] * _cosVal[i*(2*k+1)]);
        b[i] = (int)(tmp / 1000 * C2arr[i]) / 100000;
    }
}

void nmsJpegIdct(const int (*a)[8], int (*b)[8])
{
    int c[8][8];
    int i;
    for (i=0; i<8; i++)
        _idctonrow(a[i],c[i]);
    _transpose(c);
    for (i=0; i<8; i++)
        _idctonrow(c[i],b[i]);
    _transpose(b);
}

void nmsJpegDct(const int (*a)[8], int (*b)[8])
{
    int c[8][8];
    int i, j;

    for (i=0; i<8; i++)
        _dctonrow(a[i],c[i]);
    _transpose(c);
    for (i=0; i<8; i++)
        _dctonrow(c[i],b[i]);
    _transpose(b);

    for (i=0; i<8; i++)
        for (j=0; j<8; j++) {
            if (b[i][j]<-1023) b[i][j]=-1023;
            if (b[i][j]>1023) b[i][j]=1023;
        }
}

#endif  /* #ifdef __NMS_JPEG_DCT_USE_FLOAT */

/* End of File */
